package com.cmdb.web.controller.system;

import java.util.List;
import java.util.ArrayList;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.Map;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.InputStream;

import com.cmdb.common.utils.SecurityUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.cmdb.common.annotation.Log;
import com.cmdb.common.core.controller.BaseController;
import com.cmdb.common.core.domain.AjaxResult;
import com.cmdb.common.enums.BusinessType;
import com.cmdb.system.domain.SysSmsDeatil;
import com.cmdb.common.core.domain.entity.SysDept;
import com.cmdb.system.service.ISysSmsDeatilService;
import com.cmdb.system.service.ISysSmsService;
import com.cmdb.system.service.ISysDeptService;
import com.cmdb.common.utils.poi.ExcelUtil;
import com.cmdb.common.core.page.TableDataInfo;
import com.cmdb.system.domain.SysFiles;
import com.cmdb.system.domain.SysSms;

/**
 * 任务列表Controller
 * 
 * @author cyq
 * @date 2025-06-14
 */
@RestController
@RequestMapping("/system/deatil")
public class SysSmsDeatilController extends BaseController
{
    private static final Logger log = LoggerFactory.getLogger(SysSmsDeatilController.class);

    @Autowired
    private ISysSmsDeatilService sysSmsDeatilService;
    
    @Autowired
    private ISysSmsService sysSmsService;
    
    @Autowired
    private ISysDeptService sysDeptService;

    /**
     * 查询任务列表列表
     */
    @PreAuthorize("@ss.hasPermi('system:deatil:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysSmsDeatil sysSmsDeatil)
    {
        startPage();
        sysSmsDeatil.setStatus("1");
        boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
        if(!admin){
            Long deptId = SecurityUtils.getDeptId();
            sysSmsDeatil.setDeptId(SecurityUtils.getDeptId());
        }
        List<SysSmsDeatil> list = sysSmsDeatilService.selectSysSmsDeatilList(sysSmsDeatil);
        return getDataTable(list);
    }

    /**
     * 导出任务列表列表
     */
    @PreAuthorize("@ss.hasPermi('system:deatil:export')")
    @Log(title = "任务列表", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysSmsDeatil sysSmsDeatil, @RequestParam(required = false) String ids, @RequestParam(required = false) Long dataId)
    {
        List<SysSmsDeatil> list;
        
        // 如果传入了ids参数，则导出指定的数据
        if (ids != null && !ids.isEmpty()) {
            String[] idArray = ids.split(",");
            List<Long> idList = new ArrayList<>();
            for (String id : idArray) {
                try {
                    idList.add(Long.parseLong(id.trim()));
                } catch (NumberFormatException e) {
                    // 忽略无效的ID
                }
            }
            if (!idList.isEmpty()) {
                list = sysSmsDeatilService.selectSysSmsDeatilByIds(idList);
            } else {
                list = new ArrayList<>();
            }
        } else if (dataId != null) {
            // 如果传入了dataId参数，则导出指定父行的所有子表格数据
            sysSmsDeatil.setDataId(dataId);
            boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
            if(!admin){
                Long deptId = SecurityUtils.getDeptId();
                sysSmsDeatil.setDeptId(SecurityUtils.getDeptId());
            }
            list = sysSmsDeatilService.selectSysSmsDeatilList(sysSmsDeatil);
        } else {
            // 否则导出所有符合条件的数据
            boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
            if(!admin){
                Long deptId = SecurityUtils.getDeptId();
                sysSmsDeatil.setDeptId(SecurityUtils.getDeptId());
            }
            list = sysSmsDeatilService.selectSysSmsDeatilList(sysSmsDeatil);
        }
        
        // 处理部门名称和文件信息
        processExportData(list);
        
        // 导出Excel格式
        ExcelUtil<SysSmsDeatil> util = new ExcelUtil<SysSmsDeatil>(SysSmsDeatil.class);
        util.exportExcel(response, list, "任务列表数据");
    }
    
    /**
     * 处理导出数据，将部门ID转换为中文名称，处理文件信息
     */
    private void processExportData(List<SysSmsDeatil> list) {
        for (SysSmsDeatil deatil : list) {
            // 处理部门名称
            if (deatil.getUser() != null && !deatil.getUser().isEmpty()) {
                try {
                    Long deptId = Long.parseLong(deatil.getUser());
                    SysDept dept = sysDeptService.selectDeptById(deptId);
                    if (dept != null) {
                        deatil.setUser(dept.getDeptName());
                    }
                } catch (NumberFormatException e) {
                    // 如果转换失败，保持原值
                }
            }
            
            // 处理文件信息
            if (deatil.getFileList() != null && !deatil.getFileList().isEmpty()) {
                StringBuilder fileLinks = new StringBuilder();
                for (int i = 0; i < deatil.getFileList().size(); i++) {
                    if (i > 0) {
                        fileLinks.append("; ");
                    }
                    String fileName = deatil.getFileList().get(i).getFileName();
                    String filePath = deatil.getFileList().get(i).getFilePath();
                    
                    // 生成指向MinIO文件的链接
                    fileLinks.append(fileName);
                }
                // 在Excel中显示可点击的文件链接
                deatil.setFileNames(fileLinks.toString());
            } else {
                deatil.setFileNames("无");
            }
        }
    }

    /**
     * 导出任务列表列表（带附件下载）
     */
    @PreAuthorize("@ss.hasPermi('system:deatil:export')")
    @Log(title = "任务列表", businessType = BusinessType.EXPORT)
    @PostMapping("/exportWithFiles")
    public void exportWithFiles(HttpServletResponse response, SysSmsDeatil sysSmsDeatil, @RequestParam(required = false) String ids, @RequestParam(required = false) Long dataId)
    {
        List<SysSmsDeatil> list;
        
        // 如果传入了ids参数，则导出指定的数据
        if (ids != null && !ids.isEmpty()) {
            String[] idArray = ids.split(",");
            List<Long> idList = new ArrayList<>();
            for (String id : idArray) {
                try {
                    idList.add(Long.parseLong(id.trim()));
                } catch (NumberFormatException e) {
                    // 忽略无效的ID
                }
            }
            if (!idList.isEmpty()) {
                list = sysSmsDeatilService.selectSysSmsDeatilByIds(idList);
            } else {
                list = new ArrayList<>();
            }
        } else if (dataId != null) {
            // 如果传入了dataId参数，则导出指定父行的所有子表格数据
            sysSmsDeatil.setDataId(dataId);
            boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
            if(!admin){
                Long deptId = SecurityUtils.getDeptId();
                sysSmsDeatil.setDeptId(SecurityUtils.getDeptId());
            }
            list = sysSmsDeatilService.selectSysSmsDeatilList(sysSmsDeatil);
        } else {
            // 否则导出所有符合条件的数据
            boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
            if(!admin){
                Long deptId = SecurityUtils.getDeptId();
                sysSmsDeatil.setDeptId(SecurityUtils.getDeptId());
            }
            list = sysSmsDeatilService.selectSysSmsDeatilList(sysSmsDeatil);
        }
        
        // 获取主列表数据，并关联子列表和文件数据
        List<SysSms> mainList = getMainListWithDetails();
        
        // 处理部门名称和文件信息
        processExportData(list);
        
        // 统计文件总数（包括主列表和子列表的文件）
        int totalFiles = 0;
        for (SysSmsDeatil deatil : list) {
            if (deatil.getFileList() != null) {
                totalFiles += deatil.getFileList().size();
            }
        }
        for (SysSms sms : mainList) {
            if (sms.getFileList() != null) {
                totalFiles += sms.getFileList().size();
            }
        }
        
        if (totalFiles == 0) {
            // 如果没有附件，只导出Excel
            ExcelUtil<SysSmsDeatil> util = new ExcelUtil<SysSmsDeatil>(SysSmsDeatil.class);
            util.exportExcel(response, list, "任务列表数据");
            return;
        }
        
        // 创建ZIP文件，包含Excel和附件
        String zipFileName = "任务列表数据_" + System.currentTimeMillis() + ".zip";
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + zipFileName + "\"");
        
        try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
            // 1. 添加Excel文件到ZIP
            addExcelToZip(zipOut, list);
            
            // 2. 添加子列表附件文件到ZIP
            addFilesToZip(zipOut, list);
            
            // 3. 添加主列表附件文件到ZIP
            addMainListFilesToZip(zipOut, mainList);
            
            log.info("导出完成: Excel文件 + {} 个附件文件", totalFiles);
        } catch (Exception e) {
            log.error("导出带附件的任务列表失败", e);
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("导出失败: " + e.getMessage());
            } catch (IOException ioException) {
                log.error("写入错误响应失败", ioException);
            }
        }
    }
    
    /**
     * 获取主列表数据，并关联子列表和文件数据
     */
    private List<SysSms> getMainListWithDetails() {
        SysSms sysSms = new SysSms();
        sysSms.setStatus("Y"); // 只获取可用的任务
        
        boolean admin = SecurityUtils.isAdmin(SecurityUtils.getUserId());
        if (!admin) {
            Long deptId = SecurityUtils.getDeptId();
            sysSms.setDeptId(deptId.toString());
        }
        
        List<SysSms> mainList = sysSmsService.selectSysSmsList(sysSms);
        
        // 为每个主列表项获取对应的子列表数据
        for (SysSms sms : mainList) {
            SysSmsDeatil deatilQuery = new SysSmsDeatil();
            deatilQuery.setDataId(sms.getId());
            deatilQuery.setStatus("1");
            
            if (!admin) {
                deatilQuery.setDeptId(SecurityUtils.getDeptId());
            }
            
            List<SysSmsDeatil> deatilList = sysSmsDeatilService.selectSysSmsDeatilList(deatilQuery);
            // 这里可以将子列表数据存储到主列表对象中，如果需要的话
        }
        
        return mainList;
    }
    
    /**
     * 将主列表的附件文件添加到ZIP中
     */
    private void addMainListFilesToZip(ZipOutputStream zipOut, List<SysSms> mainList) throws IOException {
        int fileCount = 0;
        int successCount = 0;
        
        for (SysSms sms : mainList) {
            if (sms.getFileList() != null && !sms.getFileList().isEmpty()) {
                for (SysFiles file : sms.getFileList()) {
                    fileCount++;
                    try {
                        // 从MinIO下载文件并添加到ZIP
                        if (addFileToZip(zipOut, file, fileCount - 1)) {
                            successCount++;
                        }
                    } catch (Exception e) {
                        log.error("添加主列表文件到ZIP失败: " + file.getFileName(), e);
                    }
                }
            }
        }
        
        log.info("主列表附件处理完成: 总计 {} 个文件，成功 {} 个", fileCount, successCount);
    }

    /**
     * 获取任务列表详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:deatil:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Integer id)
    {
        return AjaxResult.success(sysSmsDeatilService.selectSysSmsDeatilById(id));
    }

    /**
     * 新增任务列表
     */
    @PreAuthorize("@ss.hasPermi('system:deatil:add')")
    @Log(title = "任务列表", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SysSmsDeatil sysSmsDeatil)
    {
        Long deptId = SecurityUtils.getDeptId();
        sysSmsDeatil.setDeptId(deptId);
        sysSmsDeatil.setUser(deptId+"");
        return toAjax(sysSmsDeatilService.insertSysSmsDeatil(sysSmsDeatil));
    }

    /**
     * 修改任务列表
     */
    @PreAuthorize("@ss.hasPermi('system:deatil:edit')")
    @Log(title = "任务列表", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SysSmsDeatil sysSmsDeatil)
    {
        return toAjax(sysSmsDeatilService.updateSysSmsDeatil(sysSmsDeatil));
    }

    /**
     * 删除任务列表
     */
    @PreAuthorize("@ss.hasPermi('system:deatil:remove')")
    @Log(title = "任务列表", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(sysSmsDeatilService.deleteSysSmsDeatilByIds(ids));
    }

    /**
     * 下载文件到指定目录
     */
    @PreAuthorize("@ss.hasPermi('system:deatil:export')")
    @PostMapping("/downloadFiles")
    public AjaxResult downloadFiles(@RequestParam String ids, @RequestParam String downloadPath) {
        try {
            // 解析ID列表
            String[] idArray = ids.split(",");
            List<Long> idList = new ArrayList<>();
            for (String id : idArray) {
                try {
                    idList.add(Long.parseLong(id.trim()));
                } catch (NumberFormatException e) {
                    // 忽略无效的ID
                }
            }
            
            if (idList.isEmpty()) {
                return AjaxResult.error("没有有效的ID");
            }
            
            // 获取数据列表
            List<SysSmsDeatil> list = sysSmsDeatilService.selectSysSmsDeatilByIds(idList);
            
            // 创建下载目录
            File downloadDir = new File(downloadPath);
            if (!downloadDir.exists()) {
                downloadDir.mkdirs();
            }
            
            // 下载文件
            int downloadCount = 0;
            List<String> downloadUrls = new ArrayList<>();
            
            for (SysSmsDeatil deatil : list) {
                if (deatil.getFileList() != null && !deatil.getFileList().isEmpty()) {
                    for (SysFiles file : deatil.getFileList()) {
                        try {
                            // 构建MinIO下载URL
                            String minioUrl = buildMinioDownloadUrl(file.getFilePath(), file.getFileName());
                            downloadUrls.add(minioUrl);
                            downloadCount++;
                        } catch (Exception e) {
                            // 记录下载失败的文件
                            log.error("构建文件下载URL失败: " + file.getFileName(), e);
                        }
                    }
                }
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("downloadCount", downloadCount);
            result.put("downloadPath", downloadPath);
            result.put("downloadUrls", downloadUrls);
            
            return AjaxResult.success("成功准备下载 " + downloadCount + " 个文件到目录: " + downloadPath, result);
            
        } catch (Exception e) {
            log.error("下载文件失败", e);
            return AjaxResult.error("下载文件失败: " + e.getMessage());
        }
    }
    
    /**
     * 构建MinIO下载URL
     */
    private String buildMinioDownloadUrl(String filePath, String fileName) {
        // 从配置中获取MinIO信息
        String minioEndpoint = "http://192.168.245.3:9000";
        String bucketName = "nyb";
        
        // 如果文件路径已经是完整的URL，直接返回
        if (filePath != null && (filePath.startsWith("http://") || filePath.startsWith("https://"))) {
            return filePath;
        }
        
        // 构建MinIO下载URL
        if (filePath != null && filePath.startsWith("/")) {
            return minioEndpoint + filePath;
        } else {
            return minioEndpoint + "/" + bucketName + "/" + (filePath != null ? filePath : fileName);
        }
    }

    /**
     * 打包下载文件
     */
    @PreAuthorize("@ss.hasPermi('system:deatil:export')")
    @PostMapping("/downloadFilesAsZip")
    public void downloadFilesAsZip(HttpServletResponse response, @RequestParam String ids) {
        try {
            // 解析ID列表
            String[] idArray = ids.split(",");
            List<Long> idList = new ArrayList<>();
            for (String id : idArray) {
                try {
                    idList.add(Long.parseLong(id.trim()));
                } catch (NumberFormatException e) {
                    // 忽略无效的ID
                }
            }
            
            if (idList.isEmpty()) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("没有有效的ID");
                return;
            }
            
            // 获取数据列表
            List<SysSmsDeatil> list = sysSmsDeatilService.selectSysSmsDeatilByIds(idList);
            
            // 统计文件总数
            int totalFiles = 0;
            for (SysSmsDeatil deatil : list) {
                if (deatil.getFileList() != null) {
                    totalFiles += deatil.getFileList().size();
                }
            }
            
            if (totalFiles == 0) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("没有找到需要下载的文件");
                return;
            }
            
            // 创建ZIP文件
            String zipFileName = "files_" + System.currentTimeMillis() + ".zip";
            response.setContentType("application/zip");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + zipFileName + "\"");
            
            // 使用ZIP输出流
            try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
                int fileCount = 0;
                int successCount = 0;
                
                for (SysSmsDeatil deatil : list) {
                    if (deatil.getFileList() != null && !deatil.getFileList().isEmpty()) {
                        for (SysFiles file : deatil.getFileList()) {
                            fileCount++;
                            try {
                                // 从MinIO下载文件并添加到ZIP
                                if (addFileToZip(zipOut, file, fileCount - 1)) {
                                    successCount++;
                                }
                            } catch (Exception e) {
                                log.error("添加文件到ZIP失败: " + file.getFileName(), e);
                            }
                        }
                    }
                }
                
                log.info("打包完成: 总计 {} 个文件，成功 {} 个", totalFiles, successCount);
            }
            
        } catch (Exception e) {
            log.error("打包下载文件失败", e);
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("打包下载失败: " + e.getMessage());
            } catch (IOException ioException) {
                log.error("写入错误响应失败", ioException);
            }
        }
    }
    
    /**
     * 将文件添加到ZIP中
     */
    private boolean addFileToZip(ZipOutputStream zipOut, SysFiles file, int index) throws IOException {
        try {
            // 从MinIO获取文件
            String fileName = file.getFileName();
            String filePath = file.getFilePath();
            
            // 构建MinIO URL
            String minioUrl = buildMinioDownloadUrl(filePath, fileName);
            
            // 创建URL连接
            URL url = new URL(minioUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(10000); // 10秒连接超时
            connection.setReadTimeout(30000);    // 30秒读取超时
            
            // 检查响应码
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                // 创建ZIP条目，处理文件名重复
                String zipEntryName = generateUniqueFileName(fileName, index);
                
                ZipEntry zipEntry = new ZipEntry(zipEntryName);
                zipOut.putNextEntry(zipEntry);
                
                // 复制文件内容到ZIP
                try (InputStream inputStream = connection.getInputStream()) {
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        zipOut.write(buffer, 0, bytesRead);
                    }
                }
                
                zipOut.closeEntry();
                log.info("成功添加文件到ZIP: {}", zipEntryName);
                return true;
            } else {
                log.warn("无法访问文件: {}, 响应码: {}", minioUrl, connection.getResponseCode());
                return false;
            }
            
        } catch (Exception e) {
            log.error("处理文件失败: " + file.getFileName(), e);
            return false;
        }
    }
    
    /**
     * 生成唯一的文件名
     */
    private String generateUniqueFileName(String originalFileName, int index) {
        if (index == 0) {
            return originalFileName;
        }
        
        // 分离文件名和扩展名
        int lastDotIndex = originalFileName.lastIndexOf('.');
        if (lastDotIndex == -1) {
            // 没有扩展名
            return originalFileName + "_" + index;
        }
        
        String nameWithoutExt = originalFileName.substring(0, lastDotIndex);
        String extension = originalFileName.substring(lastDotIndex);
        return nameWithoutExt + "_" + index + extension;
    }

    /**
     * 将Excel文件添加到ZIP中
     */
    private void addExcelToZip(ZipOutputStream zipOut, List<SysSmsDeatil> list) throws IOException {
        // 创建Excel文件
        ExcelUtil<SysSmsDeatil> util = new ExcelUtil<SysSmsDeatil>(SysSmsDeatil.class);
        
        // 创建临时文件
        String excelFileName = "任务列表数据.xlsx";
        ZipEntry excelEntry = new ZipEntry(excelFileName);
        zipOut.putNextEntry(excelEntry);
        
        // 初始化Excel数据
        util.init(list, "任务列表数据", "任务列表数据", com.cmdb.common.annotation.Excel.Type.EXPORT);
        
        // 直接写入ZIP流
        util.exportExcelToStream(zipOut);
        
        zipOut.closeEntry();
        log.info("成功添加Excel文件到ZIP: {}", excelFileName);
    }
    
    /**
     * 将附件文件添加到ZIP中
     */
    private void addFilesToZip(ZipOutputStream zipOut, List<SysSmsDeatil> list) throws IOException {
        int fileCount = 0;
        int successCount = 0;
        
        for (SysSmsDeatil deatil : list) {
            if (deatil.getFileList() != null && !deatil.getFileList().isEmpty()) {
                for (SysFiles file : deatil.getFileList()) {
                    fileCount++;
                    try {
                        // 从MinIO下载文件并添加到ZIP
                        if (addFileToZip(zipOut, file, fileCount - 1)) {
                            successCount++;
                        }
                    } catch (Exception e) {
                        log.error("添加文件到ZIP失败: " + file.getFileName(), e);
                    }
                }
            }
        }
        
        log.info("附件处理完成: 总计 {} 个文件，成功 {} 个", fileCount, successCount);
    }
}
